#include "Clipper.h"
#include "Definiciones.h"
#include <cmath>
#include <vector>

#define INFINITO  2147483647

Clipper::Clipper() {}



std::vector<Punto>  Clipper::clip( std::vector<Punto>& puntos){
       std::vector<Punto> puntosRecortados;


     float xo1,yo1;
     float x0 = puntos[0].x();
     float x1 = 0;
     float y0 = puntos[0].y();
     float y1 = 0;


     float xIn, xOut, yIn, yOut;
     float tOut1, tIn2, tOut2;
     float tInX, tOutX, tInY, tOutY;
     float dX, dY;
     unsigned i;

     for(i=0; i<puntos.size();i++){

	  xo1=x1=puntos[i].x();
	  yo1=y1=puntos[i].y();

	  dX=x1-x0;
	  dY=y1-y0;

	  if((dX > 0) || (dX == 0 && x0 > LimDer)) {
	       xIn = LimIzq; xOut = LimDer;
	  } else{
	       xIn = LimDer; xOut = LimIzq;
	  }
	  if((dY > 0) || (dY == 0 && y0 > LimSup)) {
	       yIn = LimInf; yOut = LimSup;
	  } else {
		    yIn = LimSup; yOut = LimInf;
	  }

	  if(dX != 0) {
	       tOutX = ((xOut - x0)*256.0) / dX;
	  } else if(x0 <= LimDer && LimIzq <= x0)
	       tOutX = INFINITO;
	  else
	       tOutX = -INFINITO;

	  if(dY != 0) {
	       tOutY = ((yOut - y0)*256.0) / dY;
	  } else if(y0 <= LimSup && LimInf <= y0)
	       tOutY = INFINITO;
	  else
	       tOutY = -INFINITO;


	  if(tOutX < tOutY) {
	       tOut1 = tOutX; tOut2 = tOutY;
	  } else {
	       tOut1 = tOutY; tOut2 = tOutX;
	  }

	  if(tOut2 > 0) {

	       if(dX != 0)
		    tInX = ((xIn - x0)*256.0) / dX;
	       else
		    tInX = -INFINITO;

	       if(dY != 0)
		    tInY = ((yIn - y0)*256.0) / dY;
	       else
		    tInY = -INFINITO;

	       if(tInX < tInY)
		    tIn2 = tInY;
	       else
		    tIn2 = tInX;

	       if(tOut1 < tIn2) {
		    if(0 < tOut1 && tOut1 <= 256) {
			  if(tInX < tInY) {
				  puntosRecortados.push_back(Punto(xOut,yIn));
			 } else {
				 puntosRecortados.push_back(Punto(xIn,yOut));
			 }
		    }

	       } else {

		    if(0 < tOut1 && tIn2 <= 256.0) {
			 if(0 <= tIn2) {
			      if(tInX > tInY) {
			    	  puntosRecortados.push_back(Punto(xIn, y0 + ((tInX * dY)/256.0)));
			      } else {
			    	  puntosRecortados.push_back(Punto(x0 + ((tInY * dX)/256.0), yIn));
			      }
			 }

			 if((1<<8) >= tOut1) {
			      if(tOutX < tOutY) {
			    	  puntosRecortados.push_back(Punto(xOut, y0 + ((tOutX * dY)/256.0)));
			      } else {
			    	  puntosRecortados.push_back(Punto(x0 + ((tOutY * dX)/256.0), yOut));
			      }
			 } else {
				 puntosRecortados.push_back(Punto(x1,y1));
			 }
		    }

	       }

	       if(0 < tOut2 && tOut2 <= 256) {
	    	   puntosRecortados.push_back(Punto(xOut,yOut));
	       }

	  }
	  x0=xo1;
	  y0=yo1;
     }

     return puntosRecortados;
}

Clipper::~Clipper() {}
